#include <gtest/gtest.h>
#include "Thread/ThreadPool.h"
#include <atomic>
#include <thread>
#include <vector>

// - BasicTaskExecution : 测试基本任务执行功能
// - PriorityTaskExecution : 测试优先任务执行顺序
// - MultiThreadAccess : 测试多线程并发访问
// - ThreadGroupBasic : 测试线程组基本功能
// - ShutdownBehavior : 测试线程池关闭行为

using namespace toolkit;
using namespace std;

class ThreadPoolTest : public testing::Test {
protected:
    void SetUp() override {
        pool = make_shared<ThreadPool>(2, ThreadPool::PRIORITY_NORMAL, false);
        threadPool = static_pointer_cast<ThreadPool>(pool);
    }

    TaskExecutor::Ptr pool;
    shared_ptr<ThreadPool> threadPool; 
};

TEST_F(ThreadPoolTest, BasicTaskExecution) {
    atomic_bool taskExecuted{false};
    
    pool->async([&]() {
        taskExecuted = true;
    });
    
    threadPool->start();
    this_thread::sleep_for(chrono::milliseconds(100));
    
    EXPECT_TRUE(taskExecuted.load());
}

TEST_F(ThreadPoolTest, PriorityTaskExecution) {
    vector<int> executionOrder;
    mutex mtx;
    
    threadPool->start();
    
    pool->async([&]() {
        lock_guard<mutex> lock(mtx);
        executionOrder.push_back(2);
    });
    
    pool->async_first([&]() {
        lock_guard<mutex> lock(mtx);
        executionOrder.push_back(1);
    });
    
    this_thread::sleep_for(chrono::milliseconds(200));
    
    ASSERT_EQ(executionOrder.size(), 2);
    EXPECT_EQ(executionOrder[0], 1);
    EXPECT_EQ(executionOrder[1], 2);
}

TEST_F(ThreadPoolTest, MultiThreadAccess) {
    const int taskCount = 100;
    atomic_int executedCount{0};
    
    threadPool->start();
    
    vector<thread> producers;
    for (int i = 0; i < 5; ++i) {
        producers.emplace_back([&]() {
            for (int j = 0; j < taskCount/5; ++j) {
                pool->async([&]() {
                    ++executedCount;
                });
            }
        });
    }
    
    for (auto& t : producers) {
        t.join();
    }
    
    // Wait for all tasks to complete
    while (executedCount.load() < taskCount) {
        this_thread::sleep_for(chrono::milliseconds(10));
    }
    
    EXPECT_EQ(executedCount.load(), taskCount);
}

TEST_F(ThreadPoolTest, ThreadGroupBasic) {
    thread_group group;
    atomic_int counter{0};
    
    group.create_thread([&]() {
        ++counter;
    });
    
    group.create_thread([&]() {
        ++counter;
    });
    
    group.join_all();
    
    EXPECT_EQ(counter.load(), 2);
    EXPECT_EQ(group.size(), 0);
}

TEST_F(ThreadPoolTest, ShutdownBehavior) {
    atomic_int executedCount{0};
    threadPool->start();
    
    // Add some tasks
    for (int i = 0; i < 5; ++i) {
        pool->async([&]() {
            this_thread::sleep_for(chrono::milliseconds(10));
            ++executedCount;
        });
    }
    
    // Wait for tasks to start executing
    this_thread::sleep_for(chrono::milliseconds(50));
    
    // Trigger shutdown
    pool.reset();
    
    // Verify at least some tasks executed
    EXPECT_GT(executedCount.load(), 0);
}